package servers;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

import org.grlea.log.SimpleLogger;

import vo.IListMessageResponse;
import vo.IMessageInfo;
import vo.yahoo.ListMessageResponse;
import vo.yahoo.MessageInfo;
import domainhandler.IDomainHandler;
//import domainhandler.pop.YahooBetaHandler;
import domainhandler.pop.RediffmailHandler;
import exception.LoginException;

public class PopService implements Runnable {

	private Socket socket;

	String username;

	String domain;

	String password;

	private static final SimpleLogger log = new SimpleLogger(PopService.class);

	public void run() {
		log.entry("thread start");
		BufferedReader d = null;
		IDomainHandler domainHandler = setDomainHandler();
		try {
			d = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			// As long as we receive data, echo that data back to the client.
			while (true) {
				String line = d.readLine();
				log.debugObject("line: ",line);
				if (line.toUpperCase().startsWith("USER")) {
					String user = line.trim()
							.substring(5, line.trim().length());
					log.debugObject("user:", user);
					setUsername(user.substring(0,user.indexOf('@')));
					setDomain(user.substring(user.indexOf('@')+1,user.length()));
					log.debug(getDomain());
					log.debug(getUsername());
					bw.write("+OK user is ok! send password please...\r\n");
					bw.flush();
				}
				else if (line.toUpperCase().startsWith("PASS")) {
					setPassword(line.trim().substring(5, line.trim().length()));
					log.debugObject("pass:", getPassword());
					// invoke the guy .. hardcoded to yahoo beta right now..
					try{
						domainHandler.logIn(getUsername(),getPassword());
					}catch(LoginException le){
						bw.write("-ERR password is incorrect!!...\r\n");
						bw.flush();
					}
					bw.write("+OK password is always right!!...\r\n");
					bw.flush();
				}
				else if (line.toUpperCase().startsWith("STAT")) {
					String statData = domainHandler.getStats();
					log.debug("STAT response: "+statData);
					if( statData == null ){
						bw.write("-ERR No folders for ur mailbox :-(!!...\r\n");
					}else bw.write("+OK "+statData+" Gotcha your folders!!...\r\n");
					bw.flush();
				}
				else if (line.toUpperCase().startsWith("LIST")) {
					IListMessageResponse resp = domainHandler.getListMessageResponse();
					if( resp == null ){
						// the data table is not yet downloaded
						domainHandler.getStats();
						resp = domainHandler.getListMessageResponse();
					}else{
						StringBuffer sbResp = new StringBuffer("+OK ");
						sbResp.append(resp.getNoOfMessages()+" Messages\r\n");
						for (int i = 0 ; i < resp.getMessageList().size(); i++) {
							IMessageInfo message = (IMessageInfo) resp.getMessageList().get(i);
							sbResp.append(""+(i+1)+" "+message.getSize()+"\r\n");
						}
						sbResp.append(".\r\n");
						log.debug("LIST response: "+sbResp);
						bw.write(sbResp.toString());
					}
					bw.flush();
				}
				else if (line.toUpperCase().startsWith("UIDL")) {
					IListMessageResponse resp = domainHandler.getListMessageResponse();
					if( resp == null ){
						// the data table is not yet downloaded
						domainHandler.getStats();
						resp = domainHandler.getListMessageResponse();
					}else{
						StringBuffer sbResp = new StringBuffer("+OK ");
						sbResp.append(resp.getNoOfMessages()+" Messages\r\n");
						for (int i = 0 ; i < resp.getMessageList().size(); i++) {
							IMessageInfo message = (IMessageInfo) resp.getMessageList().get(i);
							sbResp.append(""+(i+1)+" "+message.getMid()+"\r\n");
						}
						sbResp.append(".\r\n");
						log.debug("UIDL response: "+sbResp);
						bw.write(sbResp.toString());
					}
					bw.flush();
				}
				else if (line.toUpperCase().startsWith("RETR")) {
					String mId = line.split(" ")[1];
					log.debug("RETR message id: "+mId);
					StringBuffer sbResp = new StringBuffer("");
					StringBuffer message = domainHandler.getMessage(Integer.parseInt(mId));
					if( message == null ){
						sbResp.append("-ERR no data");
					}else{
						String paddedStr = message.toString().replace("[^\r]\n", "\r\n");
						paddedStr += "\r\n.\r\n";  //msg end
						sbResp.append("+OK "+paddedStr.length()+"\r\n");
						sbResp.append(paddedStr);
					}
					log.debug("RETR response: "+sbResp);
					bw.write(sbResp.toString());
					bw.flush();
				}
				else if (line.toUpperCase().startsWith("TOP")) {
//					String mId = line.split(" ")[1];
//					log.debug("TOP message id: "+mId);
//					StringBuffer sbResp = new StringBuffer("");
//					String message = ((YahooBetaHandler)domainHandler).getHeader(Integer.parseInt(mId));
//					if( message == null ){
//						sbResp.append("-ERR no data");
//					}else{
//						message += ".\r\n";  //msg end
//						sbResp.append("+OK "+message.length()+"\r\n");
//						sbResp.append(message);
//					}
//					log.debug("TOP response: "+sbResp);
//					bw.write(sbResp.toString());
//					bw.flush();
				}
			else if (line.toUpperCase().startsWith("QUIT")) {
					bw.write("+OK quitting!\r\n");
					log.debug("quiting the thread");
					getSocket().close();
					break;
				}
				else if (line.toUpperCase().startsWith("AUTH")) {
					bw.write("-ERR I have no AUTH imple.. u come anyways!\r\n");
					bw.flush();
					log.debug("AUTH failed. not supported");
				}
				else if (line.toUpperCase().startsWith("CAPA")) {
					bw.write("+OK \r\nUSER\r\nUIDL\r\nTOP\r\n.\r\n");
					bw.flush();
					log.debug("CAPAbilities are made known");
				}

			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		log.exit("thread end");
	}

	private IDomainHandler setDomainHandler() {
		// this is THE hardcoing!!
		return new RediffmailHandler();
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public String getDomain() {
		return domain;
	}

	public void setDomain(String domain) {
		this.domain = domain;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

}
